
import java.util.ArrayList;
import java.util.List;

import data.Tuple;
import helper.Tools;

public class Closeuncertainty 
{
	/**
	 * 
	 */
	public static double do_simulation(int n, double k, double pe, int times, int tuple_num)
	{
		Tuple t1;
		Tuple t2;
		/*
		Tuple tuples[]=new Tuple[tuple_num];
		
		double p=0;
		for(int i=0;i<times;i++)
		{
			int count=0;
			for(int j=0;j<tuple_num;j++)
			{
				tuples[j]=new Tuple(n,k,pe,Tuple.CLOSE); 
			}
			
			for(int j=0;j<tuple_num;j++)
			{
				for(int m=0;m<tuple_num;m++)
				{
					if(tuples[j].is_order_changed(tuples[m]))
					{
						count++;
					}

				}
			}
			p=p+1.0*count/tuple_num/tuple_num;
		}
		
		return p/times;
		*/
		
		int count=0;
		for(int i=0;i<times;i++)
		{
			t1=new Tuple(n,k,pe,Tuple.CLOSE);
			t2=new Tuple(n,k,pe,Tuple.CLOSE);
			
			if(t1.is_order_changed(t2))
			{
				//System.out.println(t1);
				//System.out.println(t2);
				count++;
			}
		}
		
		return 1.0*count/times;

	}
	public static double do_deduction(double k, double pe)
	{
		double ph,pg;
		double change;
		
		if(k>=1)
		{
			ph=1.0/3.0;
			pg=1.0/2.0;
		}
		else if(0.5<=k && k<=1.0)
		{
			ph=2*k*k*k/3.0+k*k/2.0-2.0*k*k*Math.log(k)-k+1.0/6.0;
			pg=-2*k*k*k+9*k*k/2.0-4*k+2+(2*k*k-4*k+3+Math.log(k))*Math.log(k);
		}
		else if(1.0/3.0<=k && k<0.5)
		{
			ph=-3*k*k/2.0+k/2.0+2.0*k*k*Math.log(2);
			pg=(-23-4*Math.log(2))/6.0*k*k+59.0/6.0*k-2.5-2*Math.log(2)+Math.log(2)*Math.log(2)-(1-Math.log(2))/3/k+1.0/48/k/k+
					(k*k-4*k+Math.log(k)+3)*Math.log((1-k)/k)+
					Tools.get_li(1-k)-Tools.get_li(k);
		}
		else if(1.0/4.0<=k && k<1.0/3.0)
		{
			ph=-3*k*k/2.0+k/2.0+2.0*k*k*Math.log(2);
			pg=(25.0/6.0-Math.log(2))*k*k-16.0*k/3.0-1.0/6.0+5.0/18.0/k+1.0/48.0/k/k+
					(4*k*k/3.0-4*k+1+1/3.0/k+Math.log(2*k))*Math.log(2*k/(1-2*k))+
					Tools.get_li(2*k)-Tools.get_li(1-2*k);
		}
		else if(0<=k && k<=0.25)
		{
			ph=-3.0*k*k/2.0+k/2.0+2.0*k*k*Math.log(2.0);
			pg=(11.0/18.0-Math.log(2))*k*k+2.0*k/3.0;
		}
		else
		{
			ph=0;
			pg=0;
		}
		
		change=2*pe*(1-pe)*ph+pe*pe*pg;
		return change;
	}
	public static void do_simulation(String path, int times, int n_min, int n_max, int n_step, double pe_min, double pe_max, double pe_step, double k_min, double k_max, double k_step)
	{
		double p_simulation;
		double p_deduction;
		double absolute_error=0;
		double relative_error=0;
		double abs_err;
		double rel_err=0;
		int count=0;
		
		List<Object> head=new ArrayList<Object>();
		head.add("n");
		head.add("pe");
		head.add("k");
		head.add("relative error");
		
		List<List<Object>> data=new ArrayList<List<Object>>();
		
		for(int n=n_min;n<=n_max;n+=n_step)
		{
			for(double pe=pe_min;pe<=pe_max;pe+=pe_step)
			{
				for(double k=k_min;k<=k_max;k+=k_step)
				{
					p_simulation=Closeuncertainty.do_simulation(n, k, pe, times,100);
					p_deduction=Closeuncertainty.do_deduction(k, pe);
					abs_err=Math.abs(p_simulation-p_deduction);
					absolute_error+=abs_err;
					if(Math.abs(p_simulation-p_deduction)<0.000000001)
					{
						rel_err=Math.abs((p_simulation-p_deduction)/(p_simulation+0.000000001));
					}
					else
					{
						rel_err=Math.abs((p_simulation-p_deduction)/(p_simulation));
					}
					relative_error+=rel_err;
					count++;
					System.out.println("CLOSE:n="+n+",pe="+pe+",k="+k+",simulation="+p_simulation+", deduction="+p_deduction+",absolute error="+Math.abs(p_simulation-p_deduction)+",relative error="+Math.abs((p_simulation-p_deduction)/(p_simulation+0.0000001)));	
					ArrayList<Object> list=new ArrayList<Object>();
					list.add(""+n);
					list.add(""+pe);
					list.add(""+k);
					list.add(""+rel_err);
					data.add(list);					
				}
			}
		}
		System.out.println("CLOSE absolute error="+absolute_error/count+",relative error="+relative_error/count);	
		Tools.create_4d_csv_data_file(head, data, path);
	}
	public static void main(String args[])
	{
		Closeuncertainty.do_simulation("D:\\projects\\eclipse\\UncertaintyModel\\close.csv", 1000000, 10000, 100000, 10000, 0.0, 1.0, 0.1, 0.2, 2.0, 0.1);
	}
	
}
